package com.google.code.ptrends.services.implementations;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.google.code.ptrends.entities.SourceCategory;
import com.google.code.ptrends.entities.SourceType;
import com.google.code.ptrends.entities.SupplierConfiguration;
import com.google.code.ptrends.services.SupplierService;

public class XmlSupplierService implements SupplierService {

	private static final Logger LOG = Logger
			.getLogger(XmlSupplierService.class);

	private Map<Integer, SupplierConfiguration> confMap = null;

	private void init() {
		confMap = new HashMap<Integer, SupplierConfiguration>();
		final DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
				.newInstance();
		try {
			final DocumentBuilder docBuilder = docBuilderFactory
					.newDocumentBuilder();
			final Document doc = docBuilder
					.parse(new File(
							"src/main/resources/com/google/code/ptrends/supplier_service_local.xml"));
			doc.getDocumentElement().normalize();
			final NodeList nodeList = doc
					.getElementsByTagName("SupplierConfiguration");
			if (nodeList != null) {
				for (int i = 0; i < nodeList.getLength(); i++) {
					final Element element = (Element) nodeList.item(i);
					final SupplierConfiguration conf = getConfigurationFromXML(element);
					if (conf != null) {
						confMap.put(conf.getSupplierID(), conf);
					}
				}
			}
		} catch (SAXException ex1) {
			LOG.error("Error parsing supplier_configuration.xml", ex1);
		} catch (IOException ex2) {
			LOG.error("Error reading supplier_configuration.xml", ex2);
		} catch (ParserConfigurationException ex3) {
			LOG.error("Error parsing supplier_configuration.xml", ex3);
		}
	}

	private SupplierConfiguration getConfigurationFromXML(final Element element) {
		final String sourceCategoryStr = getTextValue(element, "sourceCategory");
		final String sourceLocation = getTextValue(element, "sourceLocation");
		final String sourceTypeStr = getTextValue(element, "sourceType");
		int supplierID = 0;
		final String processorType = getTextValue(element, "processorType");

		try {
			supplierID = getIntValue(element, "supplierID");
		} catch (NumberFormatException ex) {
			LOG.error("Error reading supplier_configuration.xml", ex);
			return null;
		}

		final SupplierConfiguration conf = new SupplierConfiguration();
		SourceCategory sourceCategory = SourceCategory
				.valueOf(sourceCategoryStr);
		SourceType sourceType = SourceType.valueOf(sourceTypeStr);

		conf.setSourceCategory(sourceCategory);
		conf.setSourceType(sourceType);
		conf.setSourceLocation(sourceLocation);
		conf.setProcessorType(processorType);
		conf.setSupplierID(supplierID);
		return conf;
	}

	private String getTextValue(final Element element, final String tagName) {
		String textVal = null;
		final NodeList nodeList = element.getElementsByTagName(tagName);
		if (nodeList != null && nodeList.getLength() > 0) {
			final Element currentElement = (Element) nodeList.item(0);
			final Node node = currentElement.getFirstChild();
			if (node != null) {
				textVal = node.getNodeValue();
			}
		}
		return textVal;
	}

	private int getIntValue(final Element element, final String tagName)
			throws NumberFormatException {
		return Integer.parseInt(getTextValue(element, tagName));
	}

	@Override
	public SupplierConfiguration getConfiguration(final int supplierID) {
		if (confMap == null) {
			init();
		}
		return confMap.get(supplierID);
	}

}
